/***************************************************************************/
// Timer.cpp
// =========
// High Resolution Timer.
// This timer is able to measure the elapsed time with 1 micro-second accuracy
// in both Windows, Linux and Unix system 
//
//
/***************************************************************************/

#include <stdlib.h>
#include <stdio.h>

#include "global.h"
#include "Timer.h"

/*******************************************/
// constructor
/*******************************************/
Timer::Timer()
{
    
#ifdef WIN32
    QueryPerformanceFrequency(&frequency);
    startCount.QuadPart = 0;
    endCount.QuadPart = 0;
#else
    startCount.tv_sec = startCount.tv_usec = 0;
    endCount.tv_sec = endCount.tv_usec = 0;
#endif
    stopped = 0;
    startTimeInMicroSec = 0;
    endTimeInMicroSec = 0;
}

/*******************************************/
// distructor
/*******************************************/
Timer::~Timer(){}

/*******************************************/
// start timer.
// startCount will be set at this point.
/*******************************************/
void Timer::start()
{
    stopped = 0; // reset stop flag
#ifdef WIN32
    QueryPerformanceCounter(&startCount);
#else
    gettimeofday(&startCount, NULL);
#endif
}

/*******************************************/
// stop the timer.
// endCount will be set at this point.
void Timer::stop()
{
    stopped = 1; // set timer stopped flag

    #ifdef WIN32
        QueryPerformanceCounter(&endCount);
    #else
        gettimeofday(&endCount, NULL);
    #endif
}

/*******************************************/
// compute elapsed time in micro-second resolution.
// other getElapsedTime will call this first, 
// then convert to correspond resolution.
/*******************************************/
double Timer::getElapsedTimeInMicroSec()
{
#ifdef WIN32
    if(!stopped)
        QueryPerformanceCounter(&endCount);

    startTimeInMicroSec = startCount.QuadPart * (1000000.0 / frequency.QuadPart);
    endTimeInMicroSec = endCount.QuadPart * (1000000.0 / frequency.QuadPart);
#else
    if(!stopped)
        gettimeofday(&endCount, NULL);

    startTimeInMicroSec = (startCount.tv_sec * 1000000.0) + startCount.tv_usec;
    endTimeInMicroSec = (endCount.tv_sec * 1000000.0) + endCount.tv_usec;
#endif

    return endTimeInMicroSec - startTimeInMicroSec;
}

/*******************************************/
// divide elapsedTimeInMicroSec by 1000
double Timer::getElapsedTimeInMilliSec()
{
    return this->getElapsedTimeInMicroSec() * 0.001;
}

/*******************************************/
// 
int Timer::getElapsedTimeInSec()
{
    return (int) ( this->getElapsedTimeInMilliSec() * 0.001) ;
}

/*******************************************/
void    Timer::wait(int millis)
{
  // start timer
  start();
  
  while (getElapsedTimeInMilliSec() < millis){}
  
}
